
#include "mbserver.h"
#include <QDebug>
#include <QDateTime>
#include <QModbusDataUnit>
#include <QModbusDevice>
#include <QModbusTcpServer>
#include <QUrl>
#include <QTimer>

CustomModbusServer::CustomModbusServer(QObject* parent)
    : QModbusTcpServer(parent)
    , m_holdingRegisters(TOTAL_REGS, 0)
    , m_inputRegisters(TOTAL_REGS, 0)
{
}

bool CustomModbusServer::writeData(const QModbusDataUnit& unit)
{
    QMutexLocker locker(&m_mutex);
    qDebug() << "[Server] writeData called - Type:" << unit.registerType()
             << "Address:" << unit.startAddress()
             << "Count:" << unit.valueCount()
             << "First value:" << (unit.valueCount() > 0 ? unit.value(0) : -1);

    if (unit.registerType() == QModbusDataUnit::HoldingRegisters) {
        for (uint i = 0; i < unit.valueCount(); ++i) {
            if (unit.startAddress() + i < static_cast<uint>(m_holdingRegisters.size())) {
                m_holdingRegisters[unit.startAddress() + i] = unit.value(i);
            }
        }
        emit dataWritten(unit.registerType(), unit.startAddress(), unit.valueCount());
        return true;
    }
    return false;
}

bool CustomModbusServer::readData(QModbusDataUnit* newData) const
{
    QMutexLocker locker(&m_mutex);
    qDebug() << "[Server] readData called - Type:" << newData->registerType()
             << "Address:" << newData->startAddress()
             << "Count:" << newData->valueCount();

    if (newData->registerType() == QModbusDataUnit::HoldingRegisters) {
        for (uint i = 0; i < newData->valueCount(); ++i) {
            if (newData->startAddress() + i < static_cast<uint>(m_holdingRegisters.size())) {
                newData->setValue(i, m_holdingRegisters[newData->startAddress() + i]);
            }
        }
        return true;
    }
    return false;
}

bool CustomModbusServer::writeDataUnit(const QModbusDataUnit& unit)
{
    qDebug() << "[Server] writeDataUnit called";
    return writeData(unit);
}

bool CustomModbusServer::readDataUnit(QModbusDataUnit* newData) const
{
    qDebug() << "[Server] readDataUnit called";
    return readData(newData);
}

QModbusResponse CustomModbusServer::processRequest(const QModbusPdu& request)
{
    qDebug() << "[Server] Processing request - Function code:" << request.functionCode();
    return QModbusTcpServer::processRequest(request);
}

bool CustomModbusServer::writeRegister(quint16 address, quint16 value)
{
    QMutexLocker locker(&m_mutex);
    if (address < static_cast<quint16>(m_holdingRegisters.size())) {
        m_holdingRegisters[address] = value;
        emit dataWritten(QModbusDataUnit::HoldingRegisters, address, 1);
        return true;
    }
    return false;
}

bool CustomModbusServer::readRegister(quint16 address, quint16* value) const
{
    QMutexLocker locker(&m_mutex);
    if (address < static_cast<quint16>(m_holdingRegisters.size())) {
        *value = m_holdingRegisters[address];
        return true;
    }
    return false;
}

ModbusServer::ModbusServer(QObject *parent)
    : QObject(parent)
    , modbusServer(nullptr)
    , m_status("Stopped")
{
    qDebug() << "[Server] Initializing ModbusServer";
    
    // 创建Modbus服务器实例
    modbusServer = new CustomModbusServer(this);
    
    // 设置服务器参数
    modbusServer->setServerAddress(1);
    
    // 连接错误信号
    connect(modbusServer, &QModbusServer::errorOccurred,
            this, &ModbusServer::handleDeviceError);
    connect(modbusServer, &QModbusServer::dataWritten,
            this, &ModbusServer::handleDataWritten);

    // 创建模拟数据更新定时器
    simulationTimer = new QTimer(this);
    connect(simulationTimer, &QTimer::timeout, this, &ModbusServer::updateSimulatedData);
    
    // 初始化设备数据
    setupInitialData();
    
    qDebug() << "[Server] Initialization completed";
}

ModbusServer::~ModbusServer()
{
    if (modbusServer) {
        modbusServer->disconnectDevice();
        delete modbusServer;
    }
}

bool ModbusServer::startServer(int port)
{
    if (!modbusServer) {
        return false;
    }

    if (modbusServer->state() != QModbusDevice::ConnectedState) {
        modbusServer->setConnectionParameter(QModbusDevice::NetworkPortParameter, port);
        if (!modbusServer->connectDevice()) {
            setStatus("Failed to start server");
            return false;
        }
        setStatus("Running");
        simulationTimer->start(5000); // 每5秒更新一次模拟数据
        emit runningChanged();
        return true;
    }
    return false;
}

void ModbusServer::stopServer()
{
    if (modbusServer) {
        simulationTimer->stop();
        modbusServer->disconnectDevice();
        setStatus("Stopped");
        emit runningChanged();
    }
}

void ModbusServer::updateData(const DeviceData& data)
{
    m_deviceData = data;
    updateModbusData();
    emit deviceDataChanged();
}

bool ModbusServer::isRunning() const
{
    return modbusServer && modbusServer->state() == QModbusDevice::ConnectedState;
}

QString ModbusServer::status() const
{
    return m_status;
}

void ModbusServer::setStatus(const QString& status)
{
    if (m_status != status) {
        m_status = status;
        emit statusChanged();
    }
}

void ModbusServer::handleDeviceError(QModbusDevice::Error error)
{
    Q_UNUSED(error)
    QString errorString = modbusServer->errorString();
    qDebug() << "[Server] Error:" << errorString;
    emit errorOccurred(errorString);
    setStatus("Error: " + errorString);
}

void ModbusServer::updateSimulatedData()
{
    // 更新时间戳
    m_deviceData.timestamp = QDateTime::currentSecsSinceEpoch();
    
    // 模拟温度变化 (20±5°C)
    m_deviceData.temperature = 20.0 + (qrand() % 100 - 50) / 10.0;
    
    // 模拟湿度变化 (50±10%)
    m_deviceData.humidity = 50.0 + (qrand() % 200 - 100) / 10.0;
    
    // 模拟压力变化 (1013±10 hPa)
    m_deviceData.pressure = 1013 + (qrand() % 21 - 10);
    
    // 更新Modbus寄存器
    updateModbusData();
    
    emit deviceDataChanged();
}

void ModbusServer::setupInitialData()
{
    m_deviceData.id = 1;
    m_deviceData.name = "Device 1";
    m_deviceData.value = 0.0;
    m_deviceData.status = true;
    m_deviceData.timestamp = QDateTime::currentSecsSinceEpoch();
    m_deviceData.temperature = 20.0;
    m_deviceData.humidity = 50.0;
    m_deviceData.pressure = 1013;
    m_deviceData.alarmStatus = 0;
    m_deviceData.description = "Test Device";
    
    updateModbusData();
}

void ModbusServer::updateModbusData()
{
    if (!modbusServer) {
        return;
    }

    QVector<quint16>& registers = modbusServer->getHoldingRegisters();

    // ID
    registers[REG_ID] = static_cast<quint16>(m_deviceData.id);

    // Name
    stringToRegisters(m_deviceData.name, &registers[REG_NAME], 10);

    // Value
    quint16 valueReg1, valueReg2;
    floatToRegisters(m_deviceData.value, valueReg1, valueReg2);
    registers[REG_VALUE] = valueReg1;
    registers[REG_VALUE + 1] = valueReg2;

    // Status
    registers[REG_STATUS] = m_deviceData.status ? 1 : 0;

    // Timestamp
    quint16 timeReg1, timeReg2;
    int32ToRegisters(m_deviceData.timestamp, timeReg1, timeReg2);
    registers[REG_TIMESTAMP] = timeReg1;
    registers[REG_TIMESTAMP + 1] = timeReg2;

    // Temperature
    quint16 tempReg1, tempReg2;
    floatToRegisters(m_deviceData.temperature, tempReg1, tempReg2);
    registers[REG_TEMPERATURE] = tempReg1;
    registers[REG_TEMPERATURE + 1] = tempReg2;

    // Humidity
    quint16 humReg1, humReg2;
    floatToRegisters(m_deviceData.humidity, humReg1, humReg2);
    registers[REG_HUMIDITY] = humReg1;
    registers[REG_HUMIDITY + 1] = humReg2;

    // Pressure
    registers[REG_PRESSURE] = static_cast<quint16>(m_deviceData.pressure);

    // Alarm Status
    registers[REG_ALARM] = static_cast<quint16>(m_deviceData.alarmStatus);

    // Description
    stringToRegisters(m_deviceData.description, &registers[REG_DESC], 15);

    // 更新寄存器
    QModbusDataUnit unit(QModbusDataUnit::HoldingRegisters, 0, registers);
    modbusServer->writeData(unit);
}

void ModbusServer::handleDataWritten(QModbusDataUnit::RegisterType type, int address, int size)
{
    qDebug() << "[Server] Data written - Type:" << type << "Address:" << address << "Size:" << size;
    
    // 更新内部数据结构
    updateDeviceDataFromRegisters();
    
    // 发送数据变化信号
    emit deviceDataChanged();
}

void ModbusServer::updateDeviceDataFromRegisters()
{
    const QVector<quint16>& registers = modbusServer->getHoldingRegisters();
    
    // 更新所有数据字段
    m_deviceData.id = registers[REG_ID];
    m_deviceData.name = registersToString(&registers[REG_NAME], 10);
    m_deviceData.value = registersToFloat(registers[REG_VALUE], registers[REG_VALUE + 1]);
    m_deviceData.status = registers[REG_STATUS] != 0;
    m_deviceData.timestamp = registersToInt32(registers[REG_TIMESTAMP], registers[REG_TIMESTAMP + 1]);
    m_deviceData.temperature = registersToFloat(registers[REG_TEMPERATURE], registers[REG_TEMPERATURE + 1]);
    m_deviceData.humidity = registersToFloat(registers[REG_HUMIDITY], registers[REG_HUMIDITY + 1]);
    m_deviceData.pressure = registers[REG_PRESSURE];
    m_deviceData.alarmStatus = registers[REG_ALARM];
    m_deviceData.description = registersToString(&registers[REG_DESC], 15);
}
